package task

import (
	"errors"
	"fmt"
	"github.com/gogf/gf/database/gredis"
	"sieve_engine/execute"
	"sieve_engine/execute/whatsapp/lib/protocol/entity"
	"sieve_engine/lib/config"
	"sieve_engine/lib/log"
	"sieve_engine/task"
	"strconv"
	"strings"
	"time"
)

type whatsappExecutor struct {
	*execute.DefaultExecutor
}

var (
	wsExecutor execute.TaskExecutorInterface = &whatsappExecutor{
		&execute.DefaultExecutor{
			Debug:                *config.Bool("sieve.ws.debug", true, "debug"),
			PrintMore:            *config.Bool("sieve.ws.print_more", true, "print more"),
			ProxyEnable:          *config.Bool("sieve.ws.proxy.enable", true, "proxy enable"),
			ProxyDebug:           *config.Bool("sieve.ws.proxy.debug", true, "proxy debug"),
			NetworkErrRetryCount: *config.Int("sieve.ws.proxy.retry_count_if_network_error", -1, "retry count if network error"),
		},
	}

	redisHost   = *config.String("sieve.redis.host", "localhost:6379", "sieve redis host")
	s1          = strings.Split(redisHost, ":")[0]
	s2, _       = strconv.Atoi(strings.Split(redisHost, ":")[1])
	redisConfig = &gredis.Config{
		Host: s1,
		Port: s2,
		Db:   *config.Int("sieve.redis.db", 0, "sieve redis db"),
		Pass: *config.String("sieve.redis.pwd", "", "sieve redis pwd"),
	}

	appCloseCh = make(chan int)
)

type whatsappBaseResultRow struct {
	Valid    bool   `json:"valid"`
	Msg      string `json:"msg"`
	Phone    string `json:"phone"`
	Business bool   `json:"business"`
}

func init() {
	var group = "default"
	gredis.SetConfig(redisConfig, group)
	execute.Register("filter", wsExecutor)
}

func getPhones(str []string) []string {

	for i := 0; i < len(str); i++ {
		str[i] = "+" + str[i]
	}
	return str
}

func (s *whatsappExecutor) Execute(params execute.TaskExecutorParams, taskProgress *task.Result) error {

	params.GorCounter.Add(-int32(params.GorCount))
	wsAuthClient := NewWhatsAppAuthClientsPoolServiceProvider(appCloseCh)
	NewWhatsAppTokenServiceProvider(appCloseCh, wsAuthClient)

	var (
		phones     = getPhones(taskProgress.Phones())
		retryCount = wsExecutor.(*whatsappExecutor).NetworkErrRetryCount
		result     entity.USyncContacts
		err        error
	)

	for j := 0; j < retryCount || retryCount == -1; j++ {
		whatsapp := wsAuthClient.GetWhatsapp(time.Duration(0))
		result, err = s.syncWhatsappContacts(phones, whatsapp)
		WhatsAppClientsProvider.ReleaseWhatsapp(whatsapp)
		if err != nil {
			log.Err(fmt.Sprintf("任务执行失败:%v", err))
			// return err
			continue
		} else {
			break
		}
	}

	if err != nil {

		for _, phone := range phones {
			taskProgress.AppendResult(phone, false)
		}
		return err
	}

	for _, c := range result {
		row := &whatsappBaseResultRow{Phone: c.Contact(), Business: c.IsBusiness()}
		ct := c.ContactType()
		if ct == "out" {
			row.Valid = false
		} else {
			account := strings.Split(c.Jid(), "@")[0]
			if account == "" {
				row.Valid = false
			} else {
				row.Valid = true
			}
		}
		//
		// if row.Valid {
		//	taskProgress.ValidCount += 1
		//	//taskProgress.results = append(taskProgress.results, fmt.Sprintf("%v>in", row.Phone))
		//	taskProgress.AppendResult(fmt.Sprintf("%v>in", row.Phone))
		// } else {
		//	//taskProgress.results = append(taskProgress.results, row.Phone)
		//	taskProgress.AppendResult(row.Phone)
		// }
		// taskProgress.FinishCount += 1

		var v = row.Phone
		if row.Valid {
			v = fmt.Sprintf("%v", row.Phone)
		}
		taskProgress.AppendResult(v, row.Valid)
	}

	return err
}

// func (s *whatsappExecutor) getApi(phone string, params TaskExecutorParams, roundTripper http.RoundTripper, reuseProxy bool) (http.RoundTripper, bool, *url.URL, error) {
//
//	whatsapp := wsAuthClient.GetWhatsapp(time.Duration(0))
//	result, err := s.syncWhatsappContacts(whatsapp.token.Country, whatsapp, request.group)
//	WhatsAppClientsProvider.ReleaseWhatsapp(whatsapp)
//	return nil, false, nil, nil
// }

func (s *whatsappExecutor) syncWhatsappContacts(phones []string, app *WhatsAppClient) (entity.USyncContacts, error) {

	sync := app.waclient.SendSyncContacts(phones)
	result, err := sync.GetResult()
	if err != nil {
		return nil, err
	}

	iqResult := result.(entity.IqResult)
	if iqResult.GetErrorEntityResult() != nil {
		code := iqResult.GetErrorEntityResult().Code()
		text := iqResult.GetErrorEntityResult().Text()
		return nil, errors.New(fmt.Sprintf("SendSyncContacts failed,code:%s,text:%s", code, text))
	}

	return iqResult.GetUSyncContacts(), nil
}
